package online

import (
	"errors"
	"server/common"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"github.com/sirupsen/logrus"
)

type OnlineService struct {
	dispatcher  common.IMsgDispatcher
	userMgr     *UserManager
	callMgr     *CallManager
	router      *gin.Engine
	serviceInfo common.ServiceInfo
}

var onlineService *OnlineService

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func NewOnlineService(dispatcher common.IMsgDispatcher) *OnlineService {
	if dispatcher == nil {
		panic("dispatcher cannot be nil")
	}
	onlineService = &OnlineService{
		dispatcher: dispatcher,
	}
	return onlineService
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *OnlineService) Init() error {
	s.serviceInfo = common.ServiceInfo{
		ServiceType: common.SERVICE_TYPE_ONLINE,
		ServiceId:   uuid.New().String(),
	}

	s.userMgr = NewUserManager()
	if s.userMgr == nil {
		return errors.New("failed to create user manager")
	}

	s.callMgr = NewCallManager()
	if s.callMgr == nil {
		return errors.New("failed to create call manager")
	}

	s.dispatcher.Register(s.serviceInfo, s)

	return nil
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *OnlineService) Start() error {
	return nil
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *OnlineService) Stop() error {
	return nil
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *OnlineService) HandleMsg(msg common.Message, from common.ServiceInfo, connId string) error {
	common.Logger(common.SERVICE_TYPE_ONLINE).WithFields(logrus.Fields{
		"msg":    common.ToJson(msg),
		"from":   from,
		"connId": connId,
	}).Info("received message in online service")

	switch msg.Cmd {
	case common.LOGIN_REQ:
		return s.handleLoginReq(msg, from, connId)
	case common.CONNECTION_CLOSED_NOTIFY:
		return s.handleConnClosedNotify(msg, from, connId)
	case common.CALL_MAKE_REQ:
		return s.handleCallMakeReq(msg, from, connId)
	case common.CALL_MAKE_ACK:
		return s.handleCallMakeAck(msg, from, connId)
	case common.CALL_END_REQ:
		return s.handleCallEndReq(msg, from, connId)
	case common.CALL_END_ACK:
		return s.handleCallEndAck(msg, from, connId)
	case common.P2P_NEGOTIATE_REQ:
		return s.handleNegotiateReq(msg, from, connId)
	case common.P2P_NEGOTIATE_RES:
		return s.handleNegotiateRes(msg, from, connId)
	case common.P2P_CANDIDATE_NOTIFY:
		return s.handleCandidateNotify(msg, from, connId)
	case common.P2P_START_PUBLISH_REQ:
		return s.handleStartPublishReq(msg, from, connId)
	case common.P2P_STOP_PUBLISH_REQ:
		return s.handleStopPublishReq(msg, from, connId)
	case common.P2P_START_PUBLISH_ACK:
		return s.handleStartPublishAck(msg, from, connId)
	case common.P2P_STOP_PUBLISH_ACK:
		return s.handleStopPublishAck(msg, from, connId)
	case common.P2P_START_SUBSCRIBE_REQ:
		return s.handleStartSubscribeReq(msg, from, connId)
	case common.P2P_START_PRODUCE_ACK:
		return s.handleStartProduceAck(msg, from, connId)
	default:
		return errors.New("unknown message type: " + msg.Cmd)
	}
}
